/*
 * @Author: tongbin.xtb
 * @Date: 2018-11-27 15:43:09
 * @Last Modified by: tongbin.xtb
 * @Last Modified time: 2018-12-03 21:56:38
 */


/* global Editor, Diagram */
// TODO: import from './bpmnUtils';
/* global drawShape, insertPoint, getControlIndexByPoint, getHoverStatus,
leaveEdge, leaveEdge, enterEdge, getBBoxCenter, middleInLine */

// const G6Editor = require('../index');
// const { Diagram } = G6Editor;
import BPMN from '../bpmn';
import { insertPoint, drawPath, middleInLine, pointInLine, getControlPointsBySourceAndTarget } from '../utils/utils';
import { getJoinPoint } from '../utils/bpmnJoinPoint';
import { saveJointMoved, handleNodeMove } from '../utils/handleNodeMove';
import { mergeLine } from '../utils/edgeUtils';


/**
 * 绘制路径
 * @param {object} group G 的图形图组
 * @param {array} path 路径
 * @param {object} style 样式
 * @return {object} keyShape
 */

BPMN.registerEdge('bpmn-base', {
  // 控制点集合
  getPath(item) {
    const source = item.getSource();
    const target = item.getTarget();
    const model = item.model;
    let helpLine;    // 辅助线，在线段移动到跟其他线段平齐后需要画一个
    // 如果因为拖拽线产生重绘
    if (model.edgeMoved && model.lastMouse) {
      // 修改路径
      // 控制点
      const cp = model.controlPoints;
      // 持有鼠标的线段
      const holdIndex = model.hold.index;
      // 移动线段后获得新的坐标
      const newPoints = [{
        x: cp[holdIndex].x + model.edgeMoved.x,
        y: cp[holdIndex].y + model.edgeMoved.y
      }, {
        x: cp[holdIndex + 1].x + model.edgeMoved.x,
        y: cp[holdIndex + 1].y + model.edgeMoved.y
      }];
      const midPoint = middleInLine(newPoints, 0);
      // 起始控制点要重新计算
      // 移动线造成在起始节点新加的点
      let sourceAdded;
      // 移动线在起始节点上的新交点
      let sourceJoint;
      // 移动线在结束节点新加的点
      let targetAdded;
      // 移动节点，在结束节点上的新交点
      let targetJoint;
      // 计算跟起始节点的新交点
      if (source) {
        ({ added: sourceAdded, joint: sourceJoint } = getJoinPoint({
          bbox: source.getBBox(),
          point: midPoint,
          vertical: model.hold.vertical,
          shape: source.model.shape
        }));
      }
      // 如果移动的是跟起始节点相连的线
      if (holdIndex === 0 && source) {
        newPoints[0] = sourceJoint;
        // 有新加的节点
        if (sourceAdded) {
          newPoints.splice(1, 0, sourceAdded);
          // 添加节点后，移动当前持有鼠标的线段
          item.model.hold.index += 1;
        }
      }
      // 计算跟结束节点的新交点
      if (target) {
        ({ added: targetAdded, joint: targetJoint } = getJoinPoint({
          bbox: target.getBBox(),
          point: midPoint,
          vertical: model.hold.vertical,
          shape: target.model.shape
        }));
      }
      // 如果移动的是跟结束节点相连的线
      if (holdIndex === cp.length - 2 && target) {
        if (sourceAdded && holdIndex === 0) {
          newPoints[2] = targetJoint;
          if (targetAdded) {
            newPoints.splice(2, 0, targetAdded);
          }
        } else {
          newPoints[1] = targetJoint;
          if (targetAdded) {
            newPoints.splice(1, 0, targetAdded);
          }
        }
      }
      model.controlPoints.splice(holdIndex, 2, ...newPoints);
      // 开始节点变动的时候，会有改动，重新赋值
      // 检查移动后，是否造成控制点在节点内部，如果在，移除掉交点前面的线
      if (source && pointInLine(sourceJoint, cp, model.hold.index)) {
        cp.splice(0, model.hold.index);
        model.hold.index = 0;
        cp[0] = sourceJoint;
      }
      // 如果移动后，造成跟结束节点相交点在线上，移除掉交点后面的线
      if (target && pointInLine(targetJoint, cp, model.hold.index)) {
        model.controlPoints.splice(model.hold.index + 1);
        cp[model.hold.index + 1] = targetJoint;
      }
      // 移动后，造成有线可以合并，要画一个辅助线
      helpLine = mergeLine(item, holdIndex);
      // 移动后，起始控制点和结束控制点会黏贴在相对位置上，为节点移动做准备
      saveJointMoved(model, source, target);
      // 跟前面的线合并
      model.lastMouse = {
        x: model.lastMouse.x + model.edgeMoved.x,
        y: model.lastMouse.y + model.edgeMoved.y
      };
    } else if (model.modifiedByMouse && model.nodeMoved) {
      // 根据移动距离重新计算
      handleNodeMove(model, source, target);
    } else if (!model.modifiedByMouse) {
      // 初始化情况，获取对应锚点
      // 通过开始节点获取结束节点/反之亦然
      const anchorIndex = model.anchorIndex;
      const { sourcePoint, targetPoint } = getControlPointsBySourceAndTarget(source, target, !model.initialed && anchorIndex);
      const points = insertPoint(sourcePoint, targetPoint);
      item.model.controlPoints = points;
      // 移除可能的nodeMoved
    }
    model.nodeMoved = undefined;
    return {
      path: this.getPathByPoints({
        points: model.controlPoints
      }),
      helpLine
    };
  },
  draw(item) {
    const group = item.getGraphicGroup();
    const model = item.model;
    const { path, helpLine } = this.getPath(item);
    const style = this.getStyle(item);
    const keyShape = drawPath(group, path, style);
    if (model.hold != null) {
      const point = middleInLine(model.controlPoints, model.hold.index);
      group.addShape('circle', {
        attrs: {
          x: point.x,
          y: point.y,
          r: 3,
          fill: 'rgb(0,182,239)'
        }
      });
    }
    if (helpLine) {
      model.helpLine = helpLine;
      model.helpLineTime = new Date().getTime();
    }
    if (!helpLine && new Date().getTime() - model.helpLineTime >= 150) {
      model.helpLine = undefined;
      model.helpLineTime = undefined;
    }
    if (model.helpLine) {
      group.addShape('path', {
        attrs: {
          path: [
            [ 'M', model.helpLine[0].x, model.helpLine[0].y ],
            [ 'L', model.helpLine[1].x, model.helpLine[1].y ]
          ],
          lineAppendWidth: 8,
          lineWidth: 1,
          strokeOpacity: 0.92,
          stroke: 'rgba(255,139,48)'
        }
      });
    }
    return keyShape;
  }
});
